#include "app_adc.h"

/* ADC unit instance for this example. */
#define ADC_UNIT                        (CM_ADC1)

/* Selects ADC channels that needed. */
#define ADC_CH_POTENTIOMETER            (ADC_CH9)
#define ADC_CH                          (ADC_CH_POTENTIOMETER)
#define ADC_CH_PORT                     (GPIO_PORT_B)
#define ADC_CH_PIN                      (GPIO_PIN_01)

/* ADC sequence to be used. */
#define ADC_SEQ                         (ADC_SEQ_A)
/* Flag of conversion end. */
#define ADC_EOC_FLAG                    (ADC_FLAG_EOCA)

/* ADC reference voltage. The voltage of pin VREFH. */
#define ADC_VREF                        (3.3F)

/* ADC accuracy(according to the resolution of ADC). */
#define ADC_ACCURACY                    (1UL << 12U)

/* Calculate the voltage(mV). */
#define ADC_CAL_VOL(adcVal)             (uint16_t)((((float32_t)(adcVal) * ADC_VREF) / ((float32_t)ADC_ACCURACY)) * 1000.F)

/* Timeout value. */
#define ADC_TIMEOUT_VAL                 (1000U)

#define ADC_CH_PORT                     (GPIO_PORT_B)
#define ADC_CH_PIN                      (GPIO_PIN_01)


// 定义全局变量（分配内存）
QueueHandle_t xADCDataQueue = NULL;
SemaphoreHandle_t xFrameDataMutex = NULL;

uint8_t uarttxbuff[1028];


int timestamp = 0;
ExtY_nczallcode_T nczallcode_Ytemp;
ExtU_nczallcode_T nczallcode_Utemp;


// int clothtestflag = 0;

static void AdcSetPinAnalogMode(void)
{
    stc_gpio_init_t stcGpioInit;

    (void)GPIO_StructInit(&stcGpioInit);
    stcGpioInit.u16PinAttr = PIN_ATTR_ANALOG;
    (void)GPIO_Init(ADC_CH_PORT, ADC_CH_PIN, &stcGpioInit);
}

static void AdcInitConfig(void)
{
    stc_adc_init_t stcAdcInit;

    /* 1. Enable ADC peripheral clock. */
    FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_ADC1, ENABLE);

    /* 2. Modify the default value depends on the application. Not needed here. */
    (void)ADC_StructInit(&stcAdcInit);

    /* 关键配置项 */
    stcAdcInit.u16Resolution = ADC_RESOLUTION_12BIT; // 明确设置为12位分辨率
    stcAdcInit.u16ScanMode = ADC_MD_SEQA_SINGLESHOT;    // 单次扫描模式
    stcAdcInit.u16DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐

    /* 3. Initializes ADC. */
    (void)ADC_Init(ADC_UNIT, &stcAdcInit);

    /* 4. ADC channel configuration. */
    /* 4.1 Set the ADC pin to analog input mode. */
    AdcSetPinAnalogMode();
    /* 4.2 Enable ADC channels. Call ADC_ChCmd() again to enable more channels if needed. */
    ADC_ChCmd(ADC_UNIT, ADC_SEQ, ADC_CH, ENABLE);

    /* 5. Set sampling time if needed. */
    ADC_SetSampleTime(ADC_UNIT, ADC_CH, 0x40U);

    /* 6. Conversion data average calculation function, if needed.
          Call ADC_ConvDataAverageChCmd() again to enable more average channels if needed. */
    ADC_ConvDataAverageConfig(ADC_UNIT, ADC_AVG_CNT8);
    ADC_ConvDataAverageChCmd(ADC_UNIT, ADC_CH, ENABLE);
}
static void AdcClockConfig(void)
{

    // static void AdcClockConfig(void)
{
#if (ADC_CLK_SEL == ADC_CLK_SYS_CLK)
    /* 使用BSP配置的PCLK2=60MHz */
    CLK_SetPeriClockSrc(CLK_PERIPHCLK_PCLK);  // 直接使用系统分频
#endif
}
}


/**
 * @brief ADC模块整体配置（时钟+初始化+通道）
 */
void AdcConfig(void)
{
    AdcClockConfig();
    AdcInitConfig();
}

static uint16_t AdcPolling(void)
{
    uint16_t u16AdcValue;
    int32_t iRet = LL_ERR;
    __IO uint32_t u32TimeCount = 0UL;

    /* Can ONLY start sequence A conversion.
       Sequence B needs hardware trigger to start conversion. */
    ADC_Start(CM_ADC1);
    do {
        if (ADC_GetStatus(CM_ADC1, ADC_FLAG_EOCA) == SET) {
            ADC_ClearStatus(CM_ADC1, ADC_FLAG_EOCA);
            iRet = LL_OK;
            break;
        }
    } while (u32TimeCount++ < 1000U);

    if (iRet == LL_OK) {
        /* Get any ADC value of sequence A channel that needed. */
        u16AdcValue = ADC_GetValue(CM_ADC1, ADC_CH9);
        // DDL_Printf("The ADC value of potentiometer is %u, voltage is %u mV\r\n",
        //            u16AdcValue, ADC_CAL_VOL(u16AdcValue));
        return u16AdcValue;           
    } else {
        ADC_Stop(CM_ADC1);
        DDL_Printf("ADC exception.\r\n");

        return 0;
    }
}


/**
 * @brief 获取32x32矩阵ADC值（优化版）
 * @note 使用HC595控制行选择，HC4067控制列选择
 */

// void get32x32AdcValue(void)
// {
//     memset(uarttxbuff,0,sizeof(uarttxbuff));
   
//     for(int row = 0; row < 32; row++) {
//         // 1. 通过HC595选择当前行
//         hc595Send4Byte(1<<row);

//         for(int col = 0; col < 32; col++) {
//             hc4067Chose1Channel32(31 - col);
//             // DDL_DelayUS(20); // 更精确的延时函数
//             uint16_t  adc_value = AdcPolling();
//             adc_value = adc_value/2;

//             if(adc_value<5){

//                 adc_value=0;
    
//             }else if(adc_value>=255){
//                     adc_value = 255;
//                 }

//             uarttxbuff[row*32+col] = adc_value;    
//         }
//     }
//     uarttxbuff[1024] = 0xAA;
//     uarttxbuff[1025] = 0x55;
//     uarttxbuff[1026] = 0x03;
//     uarttxbuff[1027] = 0x99;
//     // USART_SendData_DMA("1",1);
    

//     USART_UART_Trans(CM_USART2,uarttxbuff,sizeof(uarttxbuff),1000);
//     // USART_SendData_DMA((char *)uarttxbuff,sizeof(uarttxbuff));
// }


void get32x32AdcValue(void)
{
   
    // for(int m=0;m<32;m++){
    //     gpio_handle.hc595Send4Byte(1<<m);
    //     for(int n=0;n<32;n++){				
    //         gpio_handle.hc4067Chose1Channel32(31-n);
            
    //         float temp = AdcPolling();
            
    //         temp=temp/2;
            
    //         if(temp<5){
    
    //         temp=0;
    
    //         }else if(temp>=255){
    
    //         temp = 255;
    
    //         }
    //         uarttxbuff[32*m+n] = temp;
    //     }		
                
    // }
    uarttxbuff[1024] = 0xAA;
    uarttxbuff[1025] = 0x55;
    uarttxbuff[1026] = 0x03;
    uarttxbuff[1027] = 0x99;

    // USART_SendData_DMA("1",1);
    

    USART_UART_Trans(CM_USART2,uarttxbuff,sizeof(uarttxbuff),1000);
    memset(uarttxbuff,0,sizeof(uarttxbuff));

    // USART_SendData_DMA((char *)uarttxbuff,sizeof(uarttxbuff));
}
ADC_HANDLE adc_handle = {
	// .init_adc = init_adc,
    NULL,
};
float frameDatatemp[1024];
//float frameDatatemp[1024] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,2,7,5,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,1,0,2,9,6,26,4,13,12,7,4,1,1,0,2,1,1,1,0,0,0,0,2,0,0,0,0,10,9,6,12,25,36,13,16,38,32,37,14,20,29,26,17,14,23,36,27,5,3,0,0,0,0,0,0,0,0,3,3,32,43,21,47,37,46,74,32,38,38,44,20,33,39,63,37,30,57,36,63,35,24,18,1,0,0,0,0,0,2,1,12,21,56,10,36,34,36,69,34,48,47,71,40,56,55,56,88,93,101,86,66,11,62,37,13,3,0,0,0,0,0,1,11,22,11,6,18,25,46,56,24,72,59,34,45,78,60,38,68,92,52,81,14,2,29,59,89,54,0,0,0,0,1,9,62,28,8,2,4,41,45,27,29,77,56,61,47,55,64,50,50,59,50,7,2,0,4,35,50,47,0,0,0,0,2,51,68,44,3,1,2,7,32,40,27,54,57,38,49,59,58,50,38,36,7,1,1,0,1,6,43,58,0,0,1,1,20,84,115,10,1,1,1,3,19,55,44,44,39,45,48,31,47,61,30,15,3,1,0,0,1,1,4,32,0,0,0,4,147,71,32,3,0,1,1,3,52,38,31,38,26,27,34,45,44,58,17,3,1,0,0,0,0,0,1,18,0,1,2,48,29,2,0,0,0,1,3,1,9,22,41,39,15,27,59,34,24,25,10,0,1,0,0,0,0,0,0,0,0,3,22,21,4,2,1,1,0,1,0,2,9,4,15,10,13,19,28,19,17,21,5,1,1,0,0,0,0,0,0,0,0,26,13,2,0,0,1,1,0,2,1,0,6,3,20,10,9,24,32,20,9,10,8,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,5,3,31,19,116,33,44,48,63,62,45,38,15,3,3,1,0,0,0,0,0,0,0,4,0,0,0,3,1,2,1,7,23,17,12,19,33,55,97,98,60,54,60,53,39,17,7,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,52,64,95,94,72,48,39,52,67,47,36,48,86,54,37,41,4,2,0,0,0,0,0,0,0,0,0,0,0,1,2,13,74,80,65,85,66,75,41,14,19,26,36,36,37,57,64,75,24,3,0,0,0,3,0,0,0,0,0,0,0,0,1,3,24,43,40,23,32,13,2,5,5,4,5,4,3,15,26,31,20,49,2,1,0,0,0,0,0,0,0,0,0,0,0,0,3,18,61,7,3,3,1,0,1,2,2,0,5,15,32,56,13,35,1,0,0,0,0,0,0,0,2,0,0,0,0,0,6,20,57,14,2,1,1,0,0,2,0,1,4,17,48,21,6,5,2,0,0,0,0,0,0,0,0,0,0,0,0,0,16,13,11,1,0,0,0,0,0,0,2,0,0,2,12,14,16,8,4,1,0,0,0,0,0,0,0,0,0,0,0,0,6,2,5,13,0,0,0,0,0,0,1,0,0,0,1,3,5,19,6,2,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,2,9,8,6,0,0,0,0,0,0,0,0,0,0,0,1,38,2,1,0,1,0,0,2,0,0,0,0,0,0,0,0,2,30,19,21,6,0,0,0,0,1,0,0,0,0,3,38,16,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,1,6,18,31,26,10,3,0,0,1,0,0,0,0,14,54,43,14,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,3,17,69,33,59,17,0,0,1,0,0,0,0,18,34,18,16,0,0,1,0,0,0,0,0,0,0,0,0,1,2,8,7,69,37,96,48,25,0,0,0,0,0,0,1,51,39,58,17,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,1,3,15,25,69,63,0,1,0,0,0,2,2,49,23,28,3,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,0,1,1,6,12,46,0,0,1,0,0,2,15,30,26,9,3,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,4,36,0};

void get_adc_frame()
{
	// int clothsum = 0;
	static int gettimeflag = 0;
	// memset(frameDatatemp,0,sizeof(frameDatatemp));//240619移动到循环外,只初始化为0一次
	gettimeflag+=1;
	
	if(((gettimeflag%500)==0)&&(netokflag==1)){
		gettimeflag=0;
		// nczallcode_U.tim = (float)protocol_handle.get_net_time(nczallcode_U.tim);
		nczallcode_U.tim = (float)1;
	}
	
	nczallcode_U.tim = (float)1;
	nczallcode_U.threshold_factor  = get_out_bed_parameter();
    nczallcode_U.continuous_on_bed_duration_minutes  = get_out_bed_warn();
    nczallcode_U.unlock_sitting_alarm_duration_minutes = get_sit_up_warn();

    
    nczallcode_U.unlock_falling_alarm_duration_minutes  = 0;
	nczallcode_U.sosPeakThreshold  = 25;

    // memset(nczallcode_U.frameData,0,sizeof(nczallcode_U.frameData));
	for(int m=0;m<32;m++){
		gpio_handle.hc595Send4Byte(1<<m);
		for(int n=0;n<32;n++){				
			gpio_handle.hc4067Chose1Channel32(31-n);
			
			float temp = AdcPolling();
			
			temp=temp/2;
			
			if(temp<5){

			temp=0;

			}else if(temp>=255){

			temp = 255;

			}
            uarttxbuff[32*m+n] = temp;
			nczallcode_U.frameData[32*m+n] = temp;
            // frameDatatemp[32*m+n] = temp;
            // clothsum+=(int)temp;
			
		}		
				
	}
    // USART_SendData_DMA((uint8_t *)frameDatatemp,sizeof(frameDatatemp));
    // USART_UART_Trans(CM_USART2,(uint8_t *)frameDatatemp,sizeof(frameDatatemp),1000);
    // USART_WriteData(CM_USART2,'A');
      // 保护共享数据拷贝
      if (xSemaphoreTake(xFrameDataMutex, portMAX_DELAY) == pdTRUE) {
        memcpy(frameDatatemp, nczallcode_U.frameData, sizeof(frameDatatemp));
        xSemaphoreGive(xFrameDataMutex);
    }

     // 发送数据到队列
     ADCDataMessage msg;
     memcpy(msg.frameData, nczallcode_U.frameData, sizeof(msg.frameData));
    //  msg.clothsum = clothsum;
     xQueueSend(xADCDataQueue, &msg, 0);  // 不阻塞，直接发送



	// if((clothsum>40000)&&(clothsum<80000))
	// 	clothtestflag = 1;
	
	// memcpy(frameDatatemp,nczallcode_U.frameData,sizeof(frameDatatemp));

	// nczallcode_step();
    // USART_SendData_DMA("8",1);
	// if((nczallcode_Y.rate!=-1)&&(nczallcode_Y.rate!=0xffffffff)){
	// 	memcpy(&nczallcode_Ytemp,&nczallcode_Y,sizeof(nczallcode_Ytemp));
	// 	adc_handle.send_2sdataflag = 1;
    //     USART_SendData_DMA("8",1);
	
	// }
	// if((nczallcode_Y.rateMin!=-1)&&(nczallcode_Y.rateMin!=0xffffffff)){

	// 	memcpy(&nczallcode_Ytemp,&nczallcode_Y,sizeof(nczallcode_Ytemp));
	// 	adc_handle.send_1mdataflag = 1;
		
	// }

}
void adc_task(void *pvParameters)
{	

	while (1) 
	{
		get_adc_frame();
        // USART_SendData_DMA("8",1);
		vTaskDelay(112);//120//
	}
}

void send_second1024_task(void *pvParameters)
{
    while (1)
    {
        get32x32AdcValue();
        vTaskDelay(1000);
    }
    
}

// void nczallcode_task(void *pvParameters) {
//     ADCDataMessage receivedMsg;
//     TickType_t xLastWakeTime = xTaskGetTickCount();
//     while (1) {
//         // 非阻塞检查队列
//         if (xQueueReceive(xADCDataQueue, &receivedMsg, 0) == pdPASS) {
//             if (xSemaphoreTake(xFrameDataMutex, portMAX_DELAY) == pdTRUE) {
//                 memcpy(frameDatatemp, receivedMsg.frameData, sizeof(frameDatatemp));
//                 xSemaphoreGive(xFrameDataMutex);
//             }
//             nczallcode_step();
//             USART_SendData_DMA("7",1);
//         }
//         // 固定周期延时（例如 50ms）
//         vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(50));
//     }
// }

void nczallcode_task(void *pvParameters) {
    ADCDataMessage receivedMsg;
    
    while (1) {

        // 等待队列数据（阻塞式）
        if (xQueueReceive(xADCDataQueue, &receivedMsg, portMAX_DELAY) == pdPASS) {
            // 拷贝数据到共享变量（受互斥锁保护）

            if (xSemaphoreTake(xFrameDataMutex, portMAX_DELAY) == pdTRUE) {
                memcpy(frameDatatemp, receivedMsg.frameData, sizeof(frameDatatemp));
                xSemaphoreGive(xFrameDataMutex);
            }
            // USART2_SendData(CM_USART2,(uint8_t *)frameDatatemp,sizeof(frameDatatemp));
            // 执行关键函数
            nczallcode_step();
            // USART_SendData_DMA("8",1);
            // 后续处理（根据实际需求）
            // if ((receivedMsg.clothsum > 40000) && (receivedMsg.clothsum < 80000)) {
            //     clothtestflag = 1;
            // }
            
            if((nczallcode_Y.rateMin!=-1)&&(nczallcode_Y.rateMin!=0xffffffff)){
        
                memcpy(&nczallcode_Ytemp,&nczallcode_Y,sizeof(nczallcode_Ytemp));
                adc_handle.send_1mdataflag = 1;
                
            }else if((nczallcode_Y.rate!=-1)&&(nczallcode_Y.rate!=0xffffffff)){
                memcpy(&nczallcode_Ytemp,&nczallcode_Y,sizeof(nczallcode_Ytemp));
                adc_handle.send_2sdataflag = 1;
                // USART_SendData_DMA("999",3);
				//protocol_handle.package_A0message((uint8_t)nczallcode_Y.current_threshold,(uint8_t)nczallcode_Y.on_bed_duration_minutes,(uint8_t)nczallcode_Y.sitting_alarm_duration_minutes,(uint8_t)nczallcode_Y.falling_alarm_duration_minutes,(uint8_t)nczallcode_Y.merged_alarm);

            }
            
            // 获取堆栈使用情况,获取堆栈
                // UBaseType_t uxHighWaterMark;
                // uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);

                //   char stack_info[100];
                // sprintf(stack_info, "Stack Usage: %u bytes\r\n", uxHighWaterMark);
                
                // // 先发送堆栈信息
                // USART_SendData_DMA((uint8_t*)stack_info, strlen(stack_info));
     
            // 每次处理完成后让出 CPU（例如延时 10ms）
            // vTaskDelay(pdMS_TO_TICKS(50));
        }
    }
}

void init_adc(void)
{
	nczallcode_initialize();
	AdcConfig();
}


/////////////=================ADC-initialize-END==/////////////////////////////////////////




